// Copyright (C) 2012 Tanmay Sinha
// All rights reserved

package org.saakshar.content.blogger;

import static org.saakshar.utils.HttpReqestUtils.*;
import static org.saakshar.utils.StringUtils.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.saakshar.content.ContentRetriever;
import org.saakshar.content.Label;
import org.saakshar.content.Post;

import android.net.Uri;
import android.util.Log;

/**
 * 
 * Retrieve content from blogger using the JSON API
 * 
 * @author tanmay
 * 
 */
public class BloggerJsonContentRetrieverV2 implements ContentRetriever {

	/** The Tag */
	private static final String TAG = BloggerJsonContentRetrieverV2.class
			.getSimpleName();

	private final String blogId;
	private final String apiKey;

	private static final String BLOGGER_JSON_BASE_URI = "https://www.googleapis.com/blogger/v2/blogs/";
	private static final String POSTS_PATH = "posts";
	private static final String FIELDS_QUERY_KEY = "fields";
	private static final String FIELDS_QUERY_VALUE = "nextPageToken,items/id,items/title,items/content,items/labels";
	private static final String API_KEY_QUERY_KEY = "key";
	private static final String PAGE_TOKEN_QUERY_KEY = "pageToken";

	/**
	 * In memory representation of the blog
	 */
	private final Map<Label, List<Post>> LABELS_POSTS_MAP = new HashMap<Label, List<Post>>();
	private final Map<String, Post> POSTS_MAP = new HashMap<String, Post>();

	public BloggerJsonContentRetrieverV2(String apiKey, String blogId) {
		this.blogId = blogId;
		this.apiKey = apiKey;
	}

	@Override
	public boolean loadContent() {
		try {
			String uriString = createFirstPageRequest().toString();
			String response = executeGetRequest(uriString);
			String nextPageToken = parsePage(response);

			while (!isBlank(nextPageToken)) {
				uriString = createNextPageRequest(nextPageToken).toString();
				response = executeGetRequest(uriString);
				nextPageToken = parsePage(response);
			}

		} catch (JSONException e) {
			Log.e(TAG, "Failed to load JSON content", e);
			return false;
		}

		return true;

	}

	@Override
	public List<Label> getLabels() {
		return new ArrayList<Label>(LABELS_POSTS_MAP.keySet());
	}

	@Override
	public List<Post> getPosts(Label label) {
		return LABELS_POSTS_MAP.get(label);
	}

	@Override
	public Post getPost(String id) {
		return POSTS_MAP.get(id);
	}

	private String parsePage(String responseString) throws JSONException {
		JSONObject jsonResponse = new JSONObject(responseString);

		String nextPageToken;
		try {
			nextPageToken = jsonResponse.getString("nextPageToken");
		} catch (JSONException e) {
			Log.d(TAG, "No next page token");
			return null;
		}

		JSONArray items = jsonResponse.getJSONArray("items");

		for (int i = 0; i < items.length(); i++) {
			JSONObject item = items.getJSONObject(i);

			String id = item.getString("id");
			String title = item.getString("title");
			String content = item.getString("content");

			try {
				JSONArray labelsArray = item.getJSONArray("labels");
				Post post = new Post(id, title, content);
				for (int j = 0; j < labelsArray.length(); j++) {
					Label label = new Label(labelsArray.getString(j));
					post.addLabel(label);

					addPost(post);
					addPostForLabel(label, post);
				}
			} catch (JSONException e) {
				Log.w(TAG, "No label found for post with title \"" + title
						+ "\". Posts without labels cannot be used.");
			}

		}

		return nextPageToken;

	}

	private void addPost(Post post) {
		POSTS_MAP.put(post.getId(), post);
	}

	private void addPostForLabel(Label label, Post post) {
		List<Post> posts = LABELS_POSTS_MAP.get(label);

		if (posts == null) {
			posts = new ArrayList<Post>();
		}

		posts.add(post);
		LABELS_POSTS_MAP.put(label, posts);
	}

	private Uri createFirstPageRequest() {
		Uri.Builder uriBuilder = Uri.parse(BLOGGER_JSON_BASE_URI).buildUpon();
		uriBuilder.appendPath(blogId);
		uriBuilder.appendPath(POSTS_PATH);
		uriBuilder.appendQueryParameter(FIELDS_QUERY_KEY, FIELDS_QUERY_VALUE);
		uriBuilder.appendQueryParameter(API_KEY_QUERY_KEY, apiKey);

		return uriBuilder.build();
	}

	private Uri createNextPageRequest(String nextPageToken) {
		Uri firstPageRequestUri = createFirstPageRequest();

		return firstPageRequestUri.buildUpon()
				.appendQueryParameter(PAGE_TOKEN_QUERY_KEY, nextPageToken)
				.build();

	}

}
